package com.inspection.service.impl;

import com.google.common.collect.Lists;
import com.inspection.constant.YesNoEnum;
import com.inspection.dao.InspectionBranchDao;
import com.inspection.dao.InspectionDepartmentDao;
import com.inspection.entity.InspectionBranchDO;
import com.inspection.entity.InspectionDepartmentDO;
import com.inspection.entity.SysUserDO;
import com.inspection.model.dto.BranchQueryDTO;
import com.inspection.model.dto.InspectionBranchDTO;
import com.inspection.service.InspectionBranchService;
import com.inspection.support.AssertUtils;
import com.inspection.support.PageHelper;
import com.inspection.support.SortHelper;
import com.inspection.support.model.BusinessBaseException;
import org.hibernate.hql.internal.classic.GroupByParser;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.*;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.persistence.criteria.Predicate;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * @author : chenjx
 * create at:  2020/11/8  7:44 下午
 */
@Service("InspectionBranchService")
public class InspectionBranchServiceImpl implements InspectionBranchService {

    @Autowired
    private InspectionBranchDao inspectionBranchDao;

    @Autowired
    private InspectionDepartmentDao inspectionDepartmentDao;

    @Override
    public List<InspectionBranchDO> getInspectionBranchList(BranchQueryDTO query) {
        Sort sort = new Sort(Sort.Direction.DESC, "id");

        InspectionBranchDO branchParam = new   InspectionBranchDO();
        branchParam.setIsDel(0);
        List<InspectionBranchDO> branches = inspectionBranchDao.findAll(Example.of(branchParam),sort);

        if(query.getNeedDetail()!=null&&query.getNeedDetail()){
            InspectionDepartmentDO departmentParam = new InspectionDepartmentDO();
            departmentParam.setIsDel(0);
            departmentParam.setIsLeafNode(YesNoEnum.YES.getVal());
            List<InspectionDepartmentDO> departments = inspectionDepartmentDao.findAll(Example.of(departmentParam));

            departments= departments.stream().filter(d-> d.getBranchId()!=null).collect(Collectors.toList());
            Map<Long, List<InspectionDepartmentDO>> branchDepartments = departments.stream().collect((Collectors.groupingBy(InspectionDepartmentDO::getBranchId)));
            branches.forEach(b->{
                List<InspectionDepartmentDO> branchDepts = branchDepartments.get(b.getId());
                b.setDepartments(branchDepts);
            });
        }

        return branches;
    }

    @Override
    public Page<InspectionBranchDO> pageInspectionBranch(BranchQueryDTO page) {
        Sort sort = SortHelper.buildSort(page);
        PageHelper check = PageHelper.check(page.getPageNo(), page.getPageSize());
        Pageable pageable = PageRequest.of(check.getOffset(), check.getPageSize(), sort);



        Page<InspectionBranchDO> branches =inspectionBranchDao.findAll((Specification<InspectionBranchDO>) (root, criteriaQuery, criteriaBuilder) -> {

            List<Predicate> predicates = Lists.newArrayList();
            predicates.add(criteriaBuilder.equal(root.get("isDel"), 0));

            if (!StringUtils.isEmpty(page.getBranchName())) {
                predicates.add(criteriaBuilder.like(root.get("branchName"), "%" + page.getBranchName() + "%"));
            }
            return criteriaBuilder.and(predicates.toArray(new Predicate[predicates.size()]));
        }, pageable);

        if(page.getNeedDetail()!=null&&page.getNeedDetail()){
            InspectionDepartmentDO departmentParam = new InspectionDepartmentDO();
            departmentParam.setIsDel(0);
            departmentParam.setIsLeafNode(YesNoEnum.YES.getVal());
            List<InspectionDepartmentDO> departments = inspectionDepartmentDao.findAll(Example.of(departmentParam));
            departments = departments.stream().filter(d -> d.getBranchId() != null).collect(Collectors.toList());
            Map<Long, List<InspectionDepartmentDO>> branchDepartments = departments.stream().collect((Collectors.groupingBy(InspectionDepartmentDO::getBranchId)));
            branches.forEach(b->{
                List<InspectionDepartmentDO> branchDepts = branchDepartments.get(b.getId());
                b.setDepartments(branchDepts);
            });
        }
        return branches;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addInspectionBranch(InspectionBranchDTO branchDTO) {
        InspectionBranchDO branchDO = new InspectionBranchDO();
        BeanUtils.copyProperties(branchDTO,branchDO);
        branchDO.setDateCreate(new Date());
        branchDO.setIsDel(0);
        inspectionBranchDao.saveAndFlush(branchDO);
        //再去部门表里面批量插入
        if(!CollectionUtils.isEmpty(branchDTO.getBranchDept())){
            for (Long deptId : branchDTO.getBranchDept()) {
                InspectionDepartmentDO dept = inspectionDepartmentDao.getOne(deptId);
                dept.setBranchId(branchDO.getId());
                inspectionDepartmentDao.saveAndFlush(dept);
            }
        }


    }

    @Override
    public InspectionBranchDO getInspectionBranch(BranchQueryDTO query) {
        AssertUtils.nonNull(query.getId(), "支部id不能为空！");
        InspectionBranchDO branchQuery = new InspectionBranchDO();
        branchQuery.setId(query.getId());
        branchQuery.setIsDel(0);
        Optional<InspectionBranchDO> branchOp = inspectionBranchDao.findOne(Example.of(branchQuery));
        if (!branchOp.isPresent()) {
            throw new BusinessBaseException("支部不存在");
        }
        InspectionBranchDO branch = branchOp.get();
        //部门列表
        InspectionDepartmentDO deptParam =new InspectionDepartmentDO();
        deptParam.setBranchId(branch.getId());
        deptParam.setIsDel(0);
        List<InspectionDepartmentDO> depts = inspectionDepartmentDao.findAll(Example.of(deptParam));
        branch.setDepartments(depts);
        return branch;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateInspectionBranch(InspectionBranchDTO branchDTO) {
        AssertUtils.nonNull(branchDTO.getId(), "支部id不能为空！");
        InspectionBranchDO branchQuery = new InspectionBranchDO();
        branchQuery.setId(branchDTO.getId());
        branchQuery.setIsDel(0);
        Optional<InspectionBranchDO> branchOp = inspectionBranchDao.findOne(Example.of(branchQuery));
        if (!branchOp.isPresent()) {
            throw new BusinessBaseException("支部不存在");
        }
        InspectionBranchDO branchUpdate = branchOp.get();
        branchUpdate.setBranchName(branchDTO.getBranchName());
        branchUpdate.setBranchDesc(branchDTO.getBranchDesc());
        inspectionBranchDao.saveAndFlush(branchUpdate);

        //删除部门中的支部id
        InspectionDepartmentDO deptParam = new InspectionDepartmentDO();
        deptParam.setBranchId(branchUpdate.getId());
        deptParam.setIsDel(0);
        List<InspectionDepartmentDO> depts = inspectionDepartmentDao.findAll(Example.of(deptParam));
        if (!CollectionUtils.isEmpty(depts)) {
            for (InspectionDepartmentDO dept : depts) {
                dept.setBranchId(null);
                inspectionDepartmentDao.saveAndFlush(dept);
            }
        }
        if (!CollectionUtils.isEmpty(branchDTO.getBranchDept())) {
            for (Long deptId : branchDTO.getBranchDept()) {
                InspectionDepartmentDO dept = inspectionDepartmentDao.getOne(deptId);
                dept.setBranchId(branchUpdate.getId());
                inspectionDepartmentDao.saveAndFlush(dept);
            }
        }

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delInspectionBranch(InspectionBranchDTO query) {
        AssertUtils.nonNull(query.getId(), "支部id不能为空！");
        InspectionBranchDO branchQuery = new InspectionBranchDO();
        branchQuery.setId(query.getId());
        branchQuery.setIsDel(0);
        Optional<InspectionBranchDO> branchOp = inspectionBranchDao.findOne(Example.of(branchQuery));
        if (!branchOp.isPresent()) {
            throw new BusinessBaseException("支部不存在");
        }
        InspectionBranchDO branchUpdate = branchOp.get();
        branchUpdate.setIsDel(1);
        inspectionBranchDao.saveAndFlush(branchUpdate);
        //删除部门中的支部id
        InspectionDepartmentDO deptParam = new InspectionDepartmentDO();
        deptParam.setBranchId(branchUpdate.getId());
        deptParam.setIsDel(0);
        List<InspectionDepartmentDO> depts = inspectionDepartmentDao.findAll(Example.of(deptParam));
        if (!CollectionUtils.isEmpty(depts)) {
            for (InspectionDepartmentDO dept : depts) {
                dept.setBranchId(null);
                inspectionDepartmentDao.saveAndFlush(dept);
            }
        }

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void batchDelInspectionBranch(InspectionBranchDTO branchDTO) {
        AssertUtils.notEmpty(branchDTO.getIdList(), "支部id不能为空！");

        List<InspectionBranchDO> branches = inspectionBranchDao.findAllById(branchDTO.getIdList());
        if (CollectionUtils.isEmpty(branches)) {
            throw new BusinessBaseException("支部不存在");
        }
        for (InspectionBranchDO branch : branches) {
            branch.setIsDel(1);
            inspectionBranchDao.saveAndFlush(branch);
        }

        //删除部门中的支部id
        List<Long> branchIsList = branches.stream().map(b -> b.getId()).collect(Collectors.toList());
        List<InspectionDepartmentDO> depts = inspectionDepartmentDao.findAllByIsDelEqualsAndBranchIdIn(0,branchIsList);
        if (!CollectionUtils.isEmpty(depts)) {
            for (InspectionDepartmentDO dept : depts) {
                dept.setBranchId(null);
                inspectionDepartmentDao.saveAndFlush(dept);
            }
        }
    }
}
